﻿using System;
using System.Runtime.InteropServices;

namespace Interop.Cpp
{
	/// <summary>
	/// Managed Foo wrapper class: Members correspond to that of the unmanaged C++ class.
	/// </summary>
	public unsafe class Foo
	{
		// Points at the unmanaged C++ class instance.

		private __FooClass* _instance;

		public Foo(string text)
		{
			_instance = (__FooClass*)Memory.Alloc(sizeof(__FooClass));
			var charsPtr = (char*)(void*)Marshal.StringToHGlobalAnsi(text);
			__FooClass.Constructor(_instance, charsPtr);
		}

		~Foo()
		{
			__FooClass.Destructor(_instance);
			Memory.Free(_instance);
			_instance = null;
		}

		public void Bar()
		{
			__FooClass.Bar(_instance);
		}

		// Represents the unmanaged class.
		[StructLayout(LayoutKind.Sequential, Pack = 4)]
		unsafe struct __FooClass
		{
			#region Object variables

			// Matches the memory layout of a C++ object.

			public IntPtr* _vtable;
			public fixed char text[20];

			#endregion

			#region Class and Member functions

			// Maps to class and member functions.

			[DllImport("lib.dll", EntryPoint = "_ZN3FooC2EPKc", CallingConvention = CallingConvention.ThisCall)]
			public extern static void Constructor(void* @this, char* text);

			[DllImport("lib.dll", EntryPoint = "_ZN3FooD2Ev", CallingConvention = CallingConvention.ThisCall)]
			public extern static void Destructor(void* @this);

			[DllImport("lib.dll", EntryPoint = "_ZN3Foo3BarEv", CallingConvention = CallingConvention.ThisCall)]
			public extern static void Bar(void* @this);

			#endregion
		}
	}

}

